﻿using System;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Xml;
using System.Collections.Generic;
using System.Threading;
using System.Text.RegularExpressions;

namespace ffmpeg
{
	public class Monitor
	{
		private string QueueFilename { get; set; }
		private string FolderToMonitor { get; set; }
		private string FfmpegPath { get; set; }
		private string FfmpegName { get; set; }
		private List<string> VideoExtensions { get; set; }
		private string VideoCodecRegex { get; set; }
		private string AudioCodecRegex { get; set; }
		private string SharedFolder { get; set; }
		//private int TimerSeconds { get; set; }

		private FileSystemWatcher watcher = null;
		private static object lockXMLCola = new object();
		private static object lockFfmpeg = new object();
		
		private static string cmdError = string.Empty;
		private static string cmdOutput = string.Empty;

		public Monitor(string queueFilename, string folderToMonitor, string ffmpegPath, string ffmpegName, List<string> videoExtensions, string videoCodecRegex, string audioCodecRegex, string sharedFoder/*, int timerSeconds*/)
		{
			this.QueueFilename = queueFilename;
			this.FolderToMonitor = folderToMonitor;
			this.VideoExtensions = videoExtensions;
			this.FfmpegPath = ffmpegPath;
			this.FfmpegName = ffmpegName;
			this.VideoCodecRegex = videoCodecRegex;
			this.AudioCodecRegex = audioCodecRegex;
			this.SharedFolder = sharedFoder;
			//this.TimerSeconds = timerSeconds;
		}

		public void Init()
		{
			watcher = new FileSystemWatcher(this.FolderToMonitor);
			watcher.Created += new FileSystemEventHandler(watcher_Created);
			watcher.Renamed += new RenamedEventHandler(watcher_Renamed);
			watcher.EnableRaisingEvents = true;
		}

		void watcher_Renamed(object sender, RenamedEventArgs e)
		{
			CheckFile(e.FullPath);
		}

		void watcher_Created(object sender, FileSystemEventArgs e)
		{
			CheckFile(e.FullPath);
		}

		void CheckFile(string fileName)
		{
			if(!File.Exists(fileName)) return;
			FileInfo fichero = new FileInfo(fileName);
			if(!this.VideoExtensions.Contains(fichero.Extension.ToLower().TrimStart(new char[]{'.'}))) return;
			Thread.Sleep(20000);
			bool encodingNeeded = true;
			lock (lockFfmpeg)
			{
				Process cmd = new Process();
				cmd.StartInfo.WorkingDirectory = this.FfmpegPath;
				cmd.StartInfo.FileName = this.FfmpegPath + this.FfmpegName;
				cmd.StartInfo.Arguments = " -i \"" + fileName + "\"";
				cmd.StartInfo.RedirectStandardError = true;
				cmd.StartInfo.RedirectStandardOutput = true;
				cmd.StartInfo.UseShellExecute = false;
				cmd.StartInfo.CreateNoWindow = false;
				cmdError = string.Empty;
				cmdOutput = string.Empty;
				cmd.Start();
				cmdError = cmd.StandardError.ReadToEnd();
				cmd.WaitForExit();
				if (CheckRegex(cmdError, this.VideoCodecRegex) && CheckRegex(cmdError, this.AudioCodecRegex)) encodingNeeded = false;
			}
			if (!encodingNeeded) return;
			lock(lockXMLCola)
			{
				XmlDocument doc = new XmlDocument();
				doc.Load(this.QueueFilename);
				bool duplicated = false;
				XmlNodeList nodos = doc.DocumentElement.SelectNodes("file");
				foreach(XmlNode nodo in nodos)
				{
					if (nodo.InnerText == fileName) duplicated = true;
				}
				if(!duplicated)
				{
					XmlNode nodoCola = doc.CreateNode(XmlNodeType.Element, "file", null);
					XmlAttribute atributoProcessing = doc.CreateAttribute("processing");
					atributoProcessing.Value = "0";
					nodoCola.InnerText = this.SharedFolder + fichero.Name;
					nodoCola.Attributes.Append(atributoProcessing);
					doc.DocumentElement.AppendChild(nodoCola);
					doc.Save(this.QueueFilename);
				}
			}
		}
		private bool CheckRegex(string text, string expresion)
		{
			Regex reg = new Regex(expresion, RegexOptions.IgnoreCase | RegexOptions.Multiline);
			bool ret = reg.IsMatch(text);
			return ret;
		}
	}
}
